﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using SPMS.Utility;

namespace SPMS.Commons.Configuration.Xml
{
    /// <summary>
    /// Xml配置节点
    /// </summary>
    /// <remarks></remarks>
    /// <history>
    /// [zanezeng]   2008-12-9 10:20    Created
    /// </history>
    public class XmlConfigurationNode : IConfigurationNode
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类<see cref="XmlConfigurationNode"/>的新实例
        /// </summary>
        /// <param name="configuration">当前配置节点的所属配置对象</param>
        /// <param name="node">包含配置信息的<see cref="XmlNode"/></param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="configuration"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="node"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [zanezeng]   2008-12-9 10:21    Created
        /// </history>
        public XmlConfigurationNode( IConfiguration configuration, XmlNode node )
            : this( configuration, null, node )
        {
        }

        /// <summary>
        /// 初始化类<see cref="XmlConfigurationNode"/>的新实例
        /// </summary>
        /// <param name="configuration">当前配置节点的所属配置对象</param>
        /// <param name="parentNode">当前配置节点的父配置节点</param>
        /// <param name="node">包含配置信息的<see cref="XmlNode"/></param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="configuration"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="node"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [zanezeng]   2008-12-9 10:21    Created
        /// </history>
        public XmlConfigurationNode( IConfiguration configuration, IConfigurationNode parentNode, XmlNode node )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( configuration, "configuration" );
            ArgumentAssert.AssertArgumentNotNull( node, "node" );

            //保存参数
            this.m_Configuration = configuration;
            this.m_ParentNode = parentNode;
            this.m_Node = node;

            //初始化
            this.Initialize( node );
        }

        #endregion

        #region ---IConfigurationNode

        /// <summary>
        /// 获得配置节点的名称
        /// </summary>
        /// <value>配置节点的名称</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-13 11:29    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-31 11:04    创建
        /// </history>
        public string Name
        {
            get
            {
                return this.m_Node.Name;
            }
        }

        /// <summary>
        /// 获得当前配置节点所属的配置
        /// </summary>
        /// <value>当前配置节点所属的配置</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-13 11:34    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-31 11:05    创建
        /// </history>
        public IConfiguration Configuration
        {
            get
            {
                return this.m_Configuration;
            }
        }

        /// <summary>
        /// 获得当前配置节点的父节点
        /// </summary>
        /// <value>当前配置节点的父节点</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-13 11:33    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-31 11:12    创建
        /// </history>
        public IConfigurationNode ParentNode
        {
            get
            {
                return this.m_ParentNode;
            }
        }

        /// <summary>
        /// 获得当前配置节点的值
        /// </summary>
        /// <value>当前配置节点的值</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-13 11:31    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-31 11:13    创建
        /// </history>
        public string Value
        {
            get
            {
                return this.GetNodeValue( this.m_Node );
            }
        }

        /// <summary>
        /// 获得当前节点的属性
        /// </summary>
        /// <value>当前节点的属性</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-13 11:28    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-31 11:14    创建
        /// </history>
        public IDictionary<string, IConfigurationAttribute> Attributes
        {
            get
            {
                return this.m_Attributes;
            }
        }

        /// <summary>
        /// 获得当前配置节点的所有子配置节点
        /// </summary>
        /// <value>当前配置节点的所有子配置节点</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-13 11:28    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-31 11:55    创建
        /// </history>
        public IList<IConfigurationNode> ChildNodes
        {
            get
            {
                return this.m_ChildNodes;
            }
        }

        #endregion

        #region ---Override Method

        /// <summary>
        /// 获得当前对象的字符串描述
        /// </summary>
        /// <returns>
        /// 当前对象的字符串描述
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-12-15 16:44    Created
        /// </history>
        public override string ToString()
        {
            //返回XML节点的字符串描述
            return this.m_Node.OuterXml;
        }

        #endregion

        #region ---Private Method

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="node">Xml配置节点</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-12-15 11:23    Created
        /// </history>
        private void Initialize( XmlNode node )
        {
            //创建属性列表
            this.m_Attributes = new Dictionary<string, IConfigurationAttribute>();

            //循环添加
            foreach (XmlAttribute attribute in node.Attributes)
            {
                //创建属性
                XmlConfigurationAttribute item = new XmlConfigurationAttribute( this, attribute.LocalName, attribute.Value );

                //添加到列表
                this.m_Attributes.Add( item.Name, item );
            }

            //创建节点列表
            this.m_ChildNodes = new List<IConfigurationNode>();

            //循环添加子节点
            foreach (XmlNode child in node.ChildNodes)
            {
                //判断是否为需要添加的节点
                if (child.NodeType == XmlNodeType.Element)
                {
                    //创建节点
                    XmlConfigurationNode item = new XmlConfigurationNode( this.Configuration, this, child );

                    //添加到列表
                    this.m_ChildNodes.Add( item );
                }
            }
        }

        /// <summary>
        /// 获得节点的值
        /// </summary>
        /// <param name="node">序号获得值的节点</param>
        /// <returns>节点的值</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-12-15 17:49    Created
        /// </history>
        private string GetNodeValue( XmlNode node )
        {
            //判断是否有子节点
            if (node.ChildNodes.Count > 0)
            {
                //如果有子节点，则判断子节点的类型是否为Text或者CDATA
                if (node.ChildNodes[0].NodeType == XmlNodeType.Text || node.ChildNodes[0].NodeType == XmlNodeType.CDATA)
                {
                    //如果子节点的类型为Text或者为CDATA，则返回子节点的值
                    return StringUtility.Trim( node.ChildNodes[0].Value );
                }
            }

            //返回节点的值
            return StringUtility.Trim( node.Value );
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 所属配置
        /// </summary>
        private IConfiguration m_Configuration;

        /// <summary>
        /// 父配置节点
        /// </summary>
        private IConfigurationNode m_ParentNode;

        /// <summary>
        /// 对应的XML配置节点
        /// </summary>
        private XmlNode m_Node;

        /// <summary>
        /// 子节点列表
        /// </summary>
        private IList<IConfigurationNode> m_ChildNodes;

        /// <summary>
        /// 配置节点的属性
        /// </summary>
        private IDictionary<string, IConfigurationAttribute> m_Attributes;

        #endregion
    }
}
